编程式安全策略配置

本章定义的注解和API提供用于配置 Servlet 容器强制的安全约束。

@ServletSecurity 注解

@ServletSecurity 提供了用于定义访问控制约束的另一种机制,相当于那些通过在便携式部署描述符中声明式或通过 ServletRegistration 接口的 setServletSecurity 方法编程式表示。Servlet 容器必须支持在实现 javax.servlet.Servlet 接口的类(和它的子类)上使用@ServletSecurity 注解。

  1. package javax.servlet.annotation;
  2. @Inherited
  3. @Documented
  4. @Target(value=TYPE)
  5. @Retention(value=RUNTIME)
  6. public @interface ServletSecurity {
  7. HttpConstraint value();
  8. HttpMethodConstraint[] httpMethodConstraints();
  9. }

TABLE 13-1 The ServletSecurity Interface

元素 描述 默认
value HttpConstraint 定义了应用到没有在httpMethodConstraints 返回的数组中表示的所有HTTP方法的保护。 @HttpConstraint
httpMethodConstraints HTTP方法的特定限制数组 {}

@HttpConstraint

@HttpConstraint 注解用在 @ServletSecurity 中表示应用到所有 HTTP 协议方法的安全约束,且 HTTP 协议方法对应的@HttpMethodConstraint 没有出现在 @ServletSecurity 注解中。

对于一个 @HttpConstraint 返回所有默认值发生在与至少一个@HttpMethodConstraint 返回不同于所有默认值的组合的特殊情况,@HttpMethodConstraint 表示没有安全约束被应用到任何 HTTP 协议方法,否则一个安全约束将应用。这个例外是确保这些潜在的非特定@HttpConstraint 使用没有产生约束,这将明确建立不受保护的访问这些方法;因为,它们没有被约束覆盖。

  1. package javax.servlet.annotation;
  2. @Documented
  3. @Retention(value=RUNTIME)
  4. public @interface HttpConstraint {
  5. ServletSecurity.EmptyRoleSemantic value();
  6. java.lang.String[] rolesAllowed();
  7. ServletSecurity.TransportGuarantee transportGuarantee();
  8. }
元素 描述 默认
value 当rolesAllowed返回一个空数组,(只)应用的默认授权语义。 PERMIT
rolesAllowed 包含授权角色的数组 {}
transportGuarantee 在连接的请求到达时必须满足的数据保护需求。 NONE

@HttpMethodConstraint

@HttpMethodConstraint 注解用在 @ServletSecurity 注解中表示在特定 HTTP 协议消息上的安全约束。

  1. package javax.servlet.annotation;
  2. @Documented
  3. @Retention(value=RUNTIME)
  4. public @interface HttpMethodConstraint {
  5. ServletSecurity.EmptyRoleSemantic value();
  6. java.lang.String[] rolesAllowed();
  7. ServletSecurity.TransportGuarantee transportGuarantee();
  8. }

TABLE 13-3 The HttpMethodConstraint Interface

元素 描述 默认
value HTTP协议方法名
emptyRoleSemantic 当rolesAllowed返回一个空数组,(只)应用的默认授权语义。 PERMIT
rolesAllowed 包含授权角色的数组 {}
transportGuarantee 在连接的请求到达时必须满足的数据保护需求。 NONE

@ServletSecurity 注解可以指定在(更准确地说,目标是) Servlet 实现类上,且根据 @Inherited 元注解定义的规则,它的值是被子类继承的。至多只有一个 @ServletSecurity 注解实例可以出现在 Servlet 实现类上,且 @ServletSecurity 注解必须不指定在(更准确地说,目标是) Java 方法上。

当一个或多个 @HttpMethodConstraint 注解定义在 @ServletSecurity注解中时,每一个 @HttpMethodConstraint 定义的 security-constraint,其应用到 @HttpMethodConstraint 中标识的 HTTP 协议方法。除了它的 @HttpConstraint 返回所有默认值、和它包含至少一个返回不同于所有默认值的 @HttpMethodConstraint 的情况之外,@ServletSecurity 注解定义另一个 security-constraint 应该到所有还没有定义相关 @HttpMethodConstraint 的 HTTP 协议方法。

定义在便携式部署描述符中的 security-constraint 元素用于对所有出现在该约束中的 url-pattern 授权。

当在便携式部署描述符中的一个 security-constraint 包含一个 url-pattern,其精确匹配一个使用@ServletSecurity注解的模式映射到的类,该注解必须在由容器在该模式上强制实施的约束上没有效果。

当为便携式部署描述符定义了 metadata-complete=true 时,@ServletSecurity 注解不会应用到部署描述符中的任何 url-pattern 映射到(任何servlet映射到)的注解类。

@ServletSecurity 注解不应用到 ServletRegistration 使用ServletContext 接口的 addServlet(String, Servlet) 方法创建的url-pattern,除非该 Servlet 是由 ServletContext 接口的createServlet 方法构建的。
除了上面列出的,当一个 Servlet 类注解了 @ServletSecurity,该注解定义的安全约束应用到所有 url-pattern 映射到的所有 Servlet 映射到的类。

当一个类没有加 @ServletSecurity 注解时,应用到从那个类映射到的Servlet 的访问策略是由合适的 security-constraint 元素确定的,如果有,在相关的便携式部署描述符,或者由约束禁止任何这样的标签,则如果有,为目标 servlet 通过 ServletRegistration 接口的setServletSecurity 方法编程式确定的。

 示例

以下示例演示了 ServletSecurity 注解的使用。

CODE EXAMPLE 13-1 for all HTTP methods, no constraints

  1. @ServletSecurity
  2. public class Example1 extends HttpServlet {
  3. }

CODE EXAMPLE 13-2 for all HTTP methods, no auth-constraint, confidential transport required

  1. @ServletSecurity(@HttpConstraint(transportGuarantee =
  2. TransportGuarantee.CONFIDENTIAL))
  3. public class Example2 extends HttpServlet {
  4. }

CODE EXAMPLE 13-3 for all HTTP methods, all access denied

  1. @ServletSecurity(@HttpConstraint(EmptyRoleSemantic.DENY))
  2. public class Example3 extends HttpServlet {
  3. }

CODE EXAMPLE 13-4 for all HTTP methods, auth-constraint requiring membership in Role R1

  1. @ServletSecurity(@HttpConstraint(rolesAllowed = "R1"))
  2. public class Example4 extends HttpServlet {
  3. }

CODE EXAMPLE 13-5 for All HTTP methods except GET and POST, no constraints; forethods GET and POST, auth-constraint requiring membership in Role R1; for POST, confidential transport required

  1. @ServletSecurity((httpMethodConstraints = {
  2. @HttpMethodConstraint(value = "GET", rolesAllowed = "R1"),
  3. @HttpMethodConstraint(value = "POST", rolesAllowed = "R1",
  4. transportGuarantee = TransportGuarantee.CONFIDENTIAL)
  5. })
  6. public class Example5 extends HttpServlet {
  7. }

CODE EXAMPLE 13-6 for all HTTP methods except GET auth-constraint requiring membership in Role R1; for GET, no constraints

  1. @ServletSecurity(value = @HttpConstraint(rolesAllowed = "R1"),
  2. httpMethodConstraints = @HttpMethodConstraint("GET"))
  3. public class Example6 extends HttpServlet {
  4. }

CODE EXAMPLE 13-7 for all HTTP methods except TRACE, auth-constraint requiring membership in Role R1; for TRACE, all access denied

  1. @ServletSecurity(value = @HttpConstraint(rolesAllowed = "R1"),
  2. httpMethodConstraints = @HttpMethodConstraint(value="TRACE",
  3. emptyRoleSemantic = EmptyRoleSemantic.DENY))
  4. public class Example7 extends HttpServlet {
  5. }

映射 @ServletSecurity 为 security-constraint

本节将介绍 @ServletSecurity 注解映射为它等价表示,security-constraint元素。这提供了使用已存在容器的 security-constraint 实施机制来简化实施。由 Servlet 容器实施的 @ServletSecurity 注解必须在实施的效果上是等价的,由容器从在本节中定义的映射产生security-constraint 元素。

@ServletSecurity 注解用于定义一个方法无关的 @HttpConstraint,且紧跟着一个包含零个或多个 @HttpMethodConstraint 规格的列表。方法无关的约束应用到那些没有定义 HTTP 特定方法约束的所有 HTTP 方法。
当没有包含 @HttpMethodConstraint 元素,@ServletSecurity 注解相当于包含一个 web-resource-collection 的单个 security-constraint 元素,且 web-resource-collection 不包含 http-method 元素,因此涉及到所有 HTTP 方法。

下面的例子展示了把一个不包含 @HttpMethodConstraint 注解的@ServletSecurity 注解表示为单个 security-constraint 元素。相关的 servlet(registration)定义的 url-pattern 元素将被包含在web-resource-collection 中, 任何包含的 auth-constraint 和 user-data-constraint 元素的存在和值,将由定义在13.4.1.3节的“映射 @HttpConstraint@HttpMethodConstraint 为XML”的映射的@HttpConstraint 的值确定。

CODE EXAMPLE 13-8 mapping @ServletSecurity with no contained
@HttpMethodConstraint

  1. @ServletSecurity(@HttpConstraint(rolesAllowed = "Role1"))
  2. <security-constraint>
  3. <web-resource-collection>
  4. <url-pattern>...</url-pattern>
  5. </web-resource-collection>
  6. <auth-constraint>
  7. <role-name>Role1</role-name>
  8. </auth-constraint>
  9. </security-constraint>

当指定了一个或多个 @HttpMethodConstraint 元素,方法无关的约束关联一个单个 security-constraint 元素,其,web-resource-collection 包含了为每一个 HTTP 方法命名在 @HttpMethodConstraint 元素中的 http-method-omission 元素。如果方法无关的约束返回所有默认值和至少一个 @HttpMethodConstraint 不是,包含 http-method-omission 元素的 security-constraint 必须不被创建。每一个 @HttpMethodConstraint 与另一种包含一个 web-resource-collection 的 security-constraint 关联,web-resource-collection 包含一个使用相应 HTTP 方法命名的 http-method 元素。

下面的例子展示了映射带有单个 @HttpMethodConstraint@ServletSecurity 注解为两种 security-constraint 元素。相应的Servlet(registration)定义的 url-pattern 元素将被包含在两种约束的 web-resource-collection 中,且任何包含的 auth-constraint 和 user-data-constraint 元素的存在和值,将由定义在13.4.1.3节的“映射 @HttpConstraint@HttpMethodConstraint 为XML”的映射关联的 @HttpConstraint@HttpMethodConstraint 的值确定。

CODE EXAMPLE 13-9 mapping @ServletSecurity with contained @HttpMethodConstraint

  1. @ServletSecurity(value=@HttpConstraint(rolesAllowed = "Role1"),
  2. httpMethodConstraints = @HttpMethodConstraint(value = "TRACE",
  3. emptyRoleSemantic = EmptyRoleSemantic.DENY))
  4. <security-constraint>
  5. <web-resource-collection>
  6. <url-pattern>...</url-pattern>
  7. <http-method-omission>TRACE</http-method-omission>
  8. </web-resource-collection>
  9. <auth-constraint>
  10. <role-name>Role1</role-name>
  11. </auth-constraint>
  12. </security-constraint>
  13. <security-constraint>
  14. <web-resource-collection>
  15. <url-pattern>...</url-pattern>
  16. <http-method>TRACE</http-method>
  17. </web-resource-collection>
  18. <auth-constraint/>
  19. </security-constraint>

映射 @HttpConstraint@HttpMethodConstraint 为 XML

本节将介绍映射映射 @HttpConstraint@HttpMethodConstraint 注解值(在 @ServletSecurity 中定义使用的)为它们等价的 auth-constraint 和 user-data-constraint 表示,这些注解共用一个通用模型用于表示用在便携式部署描述符中的 auth-constraint 和 user-data-constraint 元素的等价形式。该模型包括以下3种元素:

  • emptyRoleSemantic
    授权语义,PERMIT或DENY,适用于在rolesAllowed中没有指定的角色时。此元素的默认值为PERMIT,且DENY不支持与非空的rolesAllowed列表结合使用。
  • rolesAllowed
    一个包含授权角色的名字列表。当该列表为空时,其含义取决于emptyRoleSemantic的值。当角色名字“”包含在允许的角色列表中时是没有特别的含义的。当特殊的角色名字“*”出现在rolesAllowed中时,它表示用户认证,不受约束的角色,是必需的和足够的。该元素的默认值是一个空列表。
  • transportGuarantee
    数据保护需求,NONE 或 CONFIDENTIAL,在连接的请求到达时必须满足。该元素与一个包含一个使用相应值的transport-guarantee的user-data-constraint是等价的。该元素的默认值是NONE。
    下面的例子展示了上述的 @HttpConstraint 模型和 web.xml 中的 auth-constraint 和 user-data-constraint 元素之间的对应关系。

CODE EXAMPLE 13-10 emptyRoleSemantic=PERMIT, rolesAllowed={}, transportGuarantee=NONE

没有 constraint

CODE EXAMPLE 13-11 emptyRoleSemantic=PERMIT, rolesAllowed={}, transportGuarantee=CONFIDENTIAL

  1. <user-data-constraint>
  2. <transport-guarantee>CONFIDENTIAL</transport-guarantee>
  3. </user-data-constraint>

CODE EXAMPLE 13-12 emptyRoleSemantic=PERMIT, rolesAllowed={Role1},transportGuarantee=NONE

  1. <auth-constraint>
  2. <security-role-name>Role1</security-role-name>
  3. </auth-constraint>

CODE EXAMPLE 13-13 emptyRoleSemantic=PERMIT, rolesAllowed={Role1},transportGuarantee=CONFIDENTIAL

  1. <auth-constraint>
  2. <security-role-name>Role1</security-role-name>
  3. </auth-constraint>
  4. <user-data-constraint>
  5. <transport-guarantee>CONFIDENTIAL</transport-guarantee>
  6. </user-data-constraint>

CODE EXAMPLE 13-14 emptyRoleSemantic=DENY, rolesAllowed={}, transportGuarantee=NONE

  1. <auth-constraint/>

CODE EXAMPLE 13-15 emptyRoleSemantic=DENY, rolesAllowed={}, transportGuarantee=CONFIDENTIAL

  1. <auth-constraint/>
  2. <user-data-constraint>
  3. <transport-guarantee>CONFIDENTIAL</transport-guarantee>
  4. </user-data-constraint>

ServletRegistration.Dynamic 的 setServletSecurity

ServletContextListener 内的 setServletSecurity 方法用于定义应用到 ServletRegistration 定义的映射的安全约束。

  1. Collection<String> setServletSecurity(ServletSecurityElement arg);

setServletSecurity 的 javax.servlet.ServletSecurityElement 参数与 ServletSecurity 接口的 @ServletSecurity 注解在结构和模型上是类似的。因此,定义在13.4.1.2节的“映射@ServletSecurity为security-constraint”的映射,应用类似的包含HttpConstraintElement 和 HttpMethodConstraintElement 值的ServletSecurityElement 映射为其等价的 security-constraint 表示。

setServletSecurity 方法返回一组 URL pattern(可能空),其已是便携式部署描述符中的 security-constraint 元素的精确目标(因此,调用是不影响的)。

如果 ServletContext 中得到的 ServletRegistration 已经被初始化了,该方法抛出 IllegalStateException。

当便携式部署描述符中的 security-constraint 包含一个 url-pattern 其精确匹配 ServletRegistration 映射的 pattern,调用ServletRegistration 的 setServletSecurity 必须对 Servlet 容器对 pattern 实施的约束没有任何影响。

除了上面列出的,包括当 Servlet 类注解了 @ServletSecurity,当调用了 ServletRegistration 的 setServletSecurity,它制定应用到registration 的 url-pattern 的安全约束。